using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.ComponentModel;
using System.Data;
using ACME.Northwind.DataTransfer;
using ACME.Northwind.Business.Objects;
using Widgetsphere.Core.DataAccess;
using System.Linq.Expressions;
using ACME.Northwind.Business.LINQ;
using Widgetsphere.Core.Util;
using System.Reflection;

namespace ACME.Northwind.DataTransfer.Extensions
{
	public static partial class SupplierExtension
	{
		#region Fill DAL

		/// <summary>
		/// Populate a DAL object from its corresponding DTO.
		/// </summary>
		/// <param name="item">The empty DAL object.</param>
		/// <param name="dtoItem">The source DTO to load.</param>
		public static void Fill(this Supplier item, SupplierDTO dtoItem)
		{
			if (dtoItem == null) throw new Exception("The Supplier DTO cannot be null.");
			if (item == null) throw new Exception("The Supplier item cannot be null.");
			DataRow dr = ((DataRow)((IWrappingClass)item).WrappedClass);
			if (dtoItem.Address == null) dr["Address"] = System.DBNull.Value;
			else dr["Address"] = dtoItem.Address;
			if (dtoItem.City == null) dr["City"] = System.DBNull.Value;
			else dr["City"] = dtoItem.City;
			dr["CompanyName"] = dtoItem.CompanyName;
			if (dtoItem.ContactName == null) dr["ContactName"] = System.DBNull.Value;
			else dr["ContactName"] = dtoItem.ContactName;
			if (dtoItem.ContactTitle == null) dr["ContactTitle"] = System.DBNull.Value;
			else dr["ContactTitle"] = dtoItem.ContactTitle;
			if (dtoItem.Country == null) dr["Country"] = System.DBNull.Value;
			else dr["Country"] = dtoItem.Country;
			if (dtoItem.Fax == null) dr["Fax"] = System.DBNull.Value;
			else dr["Fax"] = dtoItem.Fax;
			if (dtoItem.HomePage == null) dr["HomePage"] = System.DBNull.Value;
			else dr["HomePage"] = dtoItem.HomePage;
			if (dtoItem.Phone == null) dr["Phone"] = System.DBNull.Value;
			else dr["Phone"] = dtoItem.Phone;
			if (dtoItem.PostalCode == null) dr["PostalCode"] = System.DBNull.Value;
			else dr["PostalCode"] = dtoItem.PostalCode;
			if (dtoItem.Region == null) dr["Region"] = System.DBNull.Value;
			else dr["Region"] = dtoItem.Region;
			dr["SupplierID"] = dtoItem.SupplierId;
		}

		#endregion

		#region Fill DTO

		/// <summary>
		/// Populate a DTO object collection from its corresponding DAL object collection.
		/// </summary>
		/// <param name="list">The destination DTO collection.</param>
		/// <param name="supplierCollection">The source DAL collection.</param>
		public static void Fill(this List<SupplierDTO> list, SupplierCollection supplierCollection)
		{
			if (supplierCollection == null) throw new Exception("The Supplier collection cannot be null.");
			if (list == null) list = new List<SupplierDTO>();
			foreach (Supplier item in supplierCollection)
			{
				SupplierDTO newItem = new SupplierDTO();
				newItem.Fill(item);
				list.Add(newItem);
			}
		}

		/// <summary>
		/// Populate a DTO object from its corresponding DAL object.
		/// </summary>
		/// <param name="item">The source DAL object.</param>
		/// <param name="dtoItem">The empty DTO to load.</param>
		public static void Fill(this SupplierDTO dtoItem, Supplier item)
		{
			if (dtoItem == null) throw new Exception("The Supplier DTO cannot be null.");
			if (item == null) throw new Exception("The Supplier item cannot be null.");
			dtoItem.SupplierId = item.SupplierId;
			dtoItem.Region = item.Region;
			dtoItem.PostalCode = item.PostalCode;
			dtoItem.Phone = item.Phone;
			dtoItem.HomePage = item.HomePage;
			dtoItem.Fax = item.Fax;
			dtoItem.Country = item.Country;
			dtoItem.ContactTitle = item.ContactTitle;
			dtoItem.ContactName = item.ContactName;
			dtoItem.CompanyName = item.CompanyName;
			dtoItem.City = item.City;
			dtoItem.Address = item.Address;
			dtoItem.CreatedDate = item.CreatedDate;
			dtoItem.CreatedBy = item.CreatedBy;
			dtoItem.ModifiedDate = item.ModifiedDate;
			dtoItem.ModifiedBy = item.ModifiedBy;
		}

		#endregion

		#region RunSelect

		/// <summary>
		/// Select all objects from store.
		/// </summary>
		public static void RunSelect(this List<SupplierDTO> list)
		{
			if (list == null) list = new List<SupplierDTO>();
			SupplierCollection retval = SupplierCollection.RunSelect();
			foreach (Supplier item in retval)
			{
				SupplierDTO newItem = new SupplierDTO();
				newItem.Fill(item);
				list.Add(newItem);
			}
		}

		/// <summary>
		/// Using the specified Where expression, execute a query against the database to return a result set.
		/// </summary>
		public static void RunSelect(this List<SupplierDTO> list, Expression<Func<SupplierQuery, bool>> where)
		{
			if (list == null) list = new List<SupplierDTO>();
			list.Fill(SupplierCollection.RunSelect(where));
		}

		#endregion

		#region RunSelect Paged

		/// <summary>
		/// Using the specified Where expression, execute a query against the database to return a paged result set.
		/// </summary>
		public static PagedQueryResults<SupplierDTO> RunSelect(this List<SupplierDTO> list, string pageSize, string page, string sortOrder, string sortColumn, string linq)
		{
			if (list == null) list = new List<SupplierDTO>();
			#region Setup Variables and Error Check
			int po;
			int rpp;

			if (!int.TryParse(page, out po)) throw new Exception("The page number number is not a valid integer!");
			if (po < 1) po = 1;

			if (!int.TryParse(pageSize, out rpp)) throw new Exception("The page size is not a valid integer!");
			if (rpp < 1) rpp = 1;

			Supplier.FieldNameConstants sortField;
			try
			{
				sortField = (Supplier.FieldNameConstants)Enum.Parse(typeof(Supplier.FieldNameConstants), sortColumn);
			}
			catch (Exception ex)
			{
				throw new Exception("The sort field is not valid!");
			}

			bool ascending = (sortOrder.ToLower() == "asc" || sortOrder.ToLower() == "ascending");
			#endregion

			PagedQueryResults<SupplierDTO> retVal = new PagedQueryResults<SupplierDTO>();
			SupplierPaging paging = new SupplierPaging();
			paging.RecordsperPage = rpp;
			paging.PageIndex = po;
			paging.OrderByList.Add(new SupplierPagingFieldItem(sortField, ascending));

			SupplierCollection dalList = null;
			if (string.IsNullOrEmpty(linq))
			{
				dalList = SupplierCollection.RunSelect(x => true, paging);
			}
			else
			{
				MethodInfo method = LINQDynamicCompile.GetLINQMethodPaged(linq, "ACME.Northwind.Business", "Supplier");
				dalList = (SupplierCollection)method.Invoke(null, new object[] { paging });
			}

			if (list == null) list = new List<SupplierDTO>();
			foreach (Supplier item in dalList)
			{
				SupplierDTO newItem = new SupplierDTO();
				newItem.Fill(item);
				list.Add(newItem);
			}

			retVal.CurrentPage = paging.PageIndex;
			double totalPages = Math.Ceiling((double)paging.RecordCount / (double)paging.RecordsperPage);
			retVal.TotalPages = (int)totalPages;
			retVal.TotalRecords = paging.RecordCount;
			retVal.GridData = list;

			return retVal;
		}

		#endregion

		#region RunSelect Paged

		/// <summary>
		/// Using the specified Where expression, execute a query against the database to return a result set.
		/// </summary>
		public static void RunSelect(this List<SupplierDTO> list, string linq)
		{
			if (list == null) list = new List<SupplierDTO>();

			SupplierCollection dalList = null;
			if (string.IsNullOrEmpty(linq))
			{
				dalList = SupplierCollection.RunSelect(x => true);
			}
			else
			{
				MethodInfo method = LINQDynamicCompile.GetLINQMethodAll(linq, "ACME.TestProj.Business", "Supplier");
				dalList = (SupplierCollection)method.Invoke(null, new object[] { });
			}

			if (list == null) list = new List<SupplierDTO>();
			foreach (Supplier item in dalList)
			{
				SupplierDTO newItem = new SupplierDTO();
				newItem.Fill(item);
				list.Add(newItem);
			}
		}

		#endregion

		#region Persist

		/// <summary>
		/// Persists this object to store.
		/// </summary>
		public static SupplierDTO Persist(this SupplierDTO supplier)
		{
			if (supplier == null) throw new Exception("The Supplier DTO cannot be null.");
			//Find this object and if not exists, create a new one
			Supplier newItem = ACME.Northwind.Business.Objects.Supplier.SelectUsingPK(supplier.SupplierId);
			SupplierCollection supplierCollection = null;
			if (newItem == null)
			{
				supplierCollection = new SupplierCollection();
				newItem = supplierCollection.NewItem();
			}
			else
			{
				supplierCollection = newItem.ParentCollection;
			}	

			//Populate the DAL and perist
			newItem.Fill(supplier);
			if (!newItem.IsParented) supplierCollection.AddItem(newItem);
			supplierCollection.Persist();

			//Re-populate the passed-in object from the DAL
			supplier.Fill(newItem);
			return supplier;
		}

		/// <summary>
		/// Persists this collection to store.
		/// </summary>
		public static bool Persist(this List<SupplierDTO> supplierList)
		{
			if (supplierList == null) throw new Exception("The Supplier DTO list cannot be null.");
			//Get all objects from the database that match PK
			SupplierCollection supplierCollection = new SupplierCollection();
			System.Collections.ArrayList keyList = new System.Collections.ArrayList();
			foreach (SupplierDTO dto in supplierList)
			{
				keyList.Add(new SupplierPrimaryKey(dto.SupplierId));
			}			
			supplierCollection.SubDomain.AddSelectCommand(new ACME.Northwind.Business.SelectCommands.SupplierSelectByPks(keyList));
			supplierCollection.SubDomain.RunSelectCommands();

			//Now find and populate the objects for saving
			foreach (SupplierDTO dto in supplierList)
			{
				Supplier supplier = (from x in (IEnumerable<Supplier>)supplierCollection
					where x.SupplierId == dto.SupplierId
					select x).FirstOrDefault();

				if (supplier == null) supplier = supplierCollection.NewItem();
				supplier.Fill(dto);
				if (!supplier.IsParented) supplierCollection.AddItem(supplier);
			}
			supplierCollection.Persist();

			//Re-populate the passed-in object from the DAL
			List<SupplierDTO> deletedList = new List<SupplierDTO>();
			foreach (SupplierDTO dto in supplierList)
			{
				Supplier supplier = (from x in (IEnumerable<Supplier>)supplierCollection
					where x.SupplierId == dto.SupplierId
					select x).FirstOrDefault();

				if (supplier != null) dto.Fill(supplier);
				else deletedList.Add(dto);
			}

			//Remove the items that are no longer there (if any)
			foreach (SupplierDTO dto in deletedList)
			{
				supplierList.Remove(dto);
			}

			return true;
		}

		#endregion

		#region Supplier Select by Column

		#endregion

		#region Supplier SelectUsingPK

		/// <summary>
		/// Select a single object from this collection by its primary key.
		/// </summary>
		public static void SelectUsingPK(this SupplierDTO supplier, int supplierid)
		{
			Supplier item = ACME.Northwind.Business.Objects.Supplier.SelectUsingPK(supplierid);
			supplier.Fill(item);
		}

		#endregion

		#region Supplier Select By Foreign Key

		#endregion

	}

}
